/**
 *  MainFrm.cpp
 *
 *  Copyright (C) 2008  David Andrs <pda@jasnapaka.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "StdAfx.h"
#include "mLasq.h"

#include "MainFrm.h"
#include "Config.h"

#include "ctrls/CePropertySheet.h"
#include "OptGeneralPg.h"
#include "InputDlg.h"

#include "helpers.h"

#include "md5/global.h"
#include "md5/MD5.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

const DWORD dwAdornmentFlags = 0; // exit button

/////////////////////////////////////////////////////////////////////////////
// CMainFrame

IMPLEMENT_DYNAMIC(CMainFrame, CFrameWnd)

BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
	//{{AFX_MSG_MAP(CMainFrame)
	ON_WM_CREATE()
	ON_WM_SETFOCUS()
	ON_COMMAND(ID_MENU_OPTIONS, OnMenuOptions)
	ON_COMMAND(ID_PLAY, OnPlay)
	ON_COMMAND(ID_MENU_CHANGESTATION, OnMenuChangestation)
	ON_UPDATE_COMMAND_UI(ID_MENU_CHANGESTATION, OnUpdateMenuChangestation)
	ON_COMMAND(ID_MENU_SKIP, OnMenuSkip)
	ON_UPDATE_COMMAND_UI(ID_MENU_SKIP, OnUpdateMenuSkip)
	ON_COMMAND(ID_MENU_TAG, OnMenuTag)
	ON_UPDATE_COMMAND_UI(ID_MENU_TAG, OnUpdateMenuTag)
	//}}AFX_MSG_MAP
	ON_MESSAGE(UWM_STATE_CHANGED, OnStateChanged)
	ON_MESSAGE(UWM_UPDATE_METADATA, OnUpdateMetaData)
	ON_MESSAGE(UWM_UPDATE_POS, OnUpdatePos)
	ON_MESSAGE(UWM_VOLUME_CHANGED, OnVolumeChanged)
	ON_MESSAGE(UWM_UPDATE_COVERART, OnUpdateCoverArt)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMainFrame construction/destruction

CMainFrame::CMainFrame()
{
}

CMainFrame::~CMainFrame()
{
}

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
		return -1;
	// create a view to occupy the client area of the frame
	if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
		CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
	{
		TRACE0("Failed to create view window\n");
		return -1;
	}

	// menu bar
	BOOL fSuccess;
	SHMENUBARINFO mbi = { 0 };

	mbi.cbSize = sizeof(mbi);
	mbi.dwFlags = SHCMBF_HMENU;
	mbi.nToolBarId = IDR_MAINFRAME;
	mbi.hInstRes = AfxGetInstanceHandle();
	mbi.hwndParent = GetSafeHwnd();

	fSuccess = SHCreateMenuBar(&mbi);
	m_hwndCmdBar = mbi.hwndMB;

	UpdateMenu();
	if (Config.AutoConnect)
		LastFM.Connect(Config.UserName, CalculateMD5(Config.Password));

	// set volume
	DWORD volume = LastFM.SndDev.GetVolume();
	m_wndView.m_ctlVolume.SetPos(volume / 0x800);

	return 0;
}

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT &cs) {
	if (!CFrameWnd::PreCreateWindow(cs))
		return FALSE;

	cs.lpszClass = AfxRegisterWndClass(0);
	return TRUE;
}


/////////////////////////////////////////////////////////////////////////////
// CMainFrame diagnostics

#ifdef _DEBUG
void CMainFrame::AssertValid() const
{
	CFrameWnd::AssertValid();
}

void CMainFrame::Dump(CDumpContext& dc) const
{
	CFrameWnd::Dump(dc);
}

#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMainFrame message handlers
void CMainFrame::OnSetFocus(CWnd* pOldWnd)
{
	// forward focus to the view window
	m_wndView.SetFocus();
}

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
	// let the view have first crack at the command
	if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;

	// otherwise, do default handling
	return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

void CMainFrame::OnMenuOptions() {
	COptGeneralPg pgGeneral;

	CCePropertySheet sheet(IDS_OPTIONS);
	sheet.AddPage(&pgGeneral);
	sheet.SetMenu(IDR_CANCEL);

	sheet.DoModal();
}

void CMainFrame::OnPlay() {
	if (LastFM.State == CLastFM::Playing || LastFM.State == CLastFM::Buffering) {
		LastFM.Stop();
		m_wndView.m_ctlProgress.SetPos(0);
	}
	else if (LastFM.State == CLastFM::Disconnected)
		LastFM.Connect(Config.UserName, CalculateMD5(Config.Password));
	else if (LastFM.State == CLastFM::Connected)
		LastFM.Play();
	else
		return;

	UpdateMenu();
}


void CMainFrame::UpdateMenu() {
	TBBUTTONINFO tbbi;
	tbbi.cbSize = sizeof(tbbi);
	tbbi.dwMask = TBIF_TEXT;
	if (LastFM.State == CLastFM::Disconnected || LastFM.State == CLastFM::Connecting)
		tbbi.pszText = _T("Connect");
	else if (LastFM.State != CLastFM::Playing && LastFM.State != CLastFM::Buffering)
		tbbi.pszText = _T("Play");
	else
		tbbi.pszText = _T("Stop");
	::SendMessage(m_hwndCmdBar, TB_SETBUTTONINFO, (WPARAM) ID_PLAY, (LPARAM) &tbbi);

	if (LastFM.State == CLastFM::Connecting)
		::SendMessage(m_hwndCmdBar, TB_ENABLEBUTTON, (WPARAM) ID_PLAY, (LPARAM) MAKELONG(FALSE, 0));
	else
		::SendMessage(m_hwndCmdBar, TB_ENABLEBUTTON, (WPARAM) ID_PLAY, (LPARAM) MAKELONG(TRUE, 0));
}

LRESULT CMainFrame::OnStateChanged(WPARAM wParam, LPARAM lParam) {
	CString strState = LastFM.StateToString();
	m_wndView.m_ctlStatus.SetWindowText(strState);
	UpdateMenu();

	return 0;
}

LRESULT CMainFrame::OnUpdateMetaData(WPARAM wParam, LPARAM lParam) {
	m_wndView.m_ctlStationName.SetWindowText(LastFM.GetStationName());

	CPlaylistEntry *pl = LastFM.GetMetaData();
	if (pl != NULL) {
		m_wndView.m_ctlTrack.SetWindowText(pl->Title);
		m_wndView.m_ctlArtist.SetWindowText(pl->Artist);
		m_wndView.m_ctlAlbum.SetWindowText(pl->Album);
	}

	m_wndView.m_ctlProgress.SetRange32(0, LastFM.GetLength());
	m_wndView.m_ctlProgress.SetPos(0);

	return 0;
}

LRESULT CMainFrame::OnUpdatePos(WPARAM wParam, LPARAM lParam) {
	DWORD pos = LastFM.GetCurPos();

	m_wndView.m_ctlProgress.SetPos(pos);

	return 0;
}

void CMainFrame::OnMenuChangestation() {
	CInputDlg dlg;

	dlg.SetCaption(IDS_CHANGE_STATION);
	dlg.m_strLabel.LoadString(IDS_FAVORITE_ARTIST);
	if (dlg.DoModal() == IDOK) {
		CWaitCursor wait;
		if (LastFM.ChangeStation(dlg.m_strInput)) {
		}
		else {
			AfxMessageBox(_T("Failed to change station"));
		}
	}
}

void CMainFrame::OnUpdateMenuChangestation(CCmdUI* pCmdUI) {
	pCmdUI->Enable(
		LastFM.State == CLastFM::Playing ||
		LastFM.State == CLastFM::Buffering ||
		LastFM.State == CLastFM::Connected);
}

void CMainFrame::OnMenuSkip() {
	LastFM.NextTrack();
}

void CMainFrame::OnUpdateMenuSkip(CCmdUI* pCmdUI) {
	pCmdUI->Enable(LastFM.State == CLastFM::Playing);
}

void CMainFrame::OnMenuTag() {
	CInputDlg dlg;

	dlg.SetCaption(IDS_TAG);
	dlg.m_strLabel.LoadString(IDS_ENTER_TAG);
	if (dlg.DoModal() == IDOK) {
		// TODO:
		// LastFM.Tag(dlg.m_strInput);
	}
}

void CMainFrame::OnUpdateMenuTag(CCmdUI* pCmdUI) {
	pCmdUI->Enable(LastFM.State == CLastFM::Playing);
}

LRESULT CMainFrame::OnVolumeChanged(WPARAM wParam, LPARAM lParam) {
	if (lParam > 0) lParam--;
	LastFM.SndDev.SetVolume(lParam);
	return 0;
}

LRESULT CMainFrame::OnUpdateCoverArt(WPARAM wParam, LPARAM lParam) {
	m_wndView.m_ctlCoverArt.Read(LastFM.GetCoverArtFileName());
	return 0;
}
